package com.cyh.core.login.service.user.impl;

import com.cyh.core.framework.common.constant.RedisConstant;
import com.cyh.core.framework.domain.dto.ResultDTO;
import com.cyh.core.framework.domain.dto.SimplePageDTO;
import com.cyh.core.framework.domain.dto.SimpleQueryDTO;
import com.cyh.core.login.entity.User;
import com.cyh.core.login.entity.UserInfo;
import com.cyh.core.login.repository.UsersRepository;
import com.cyh.core.login.service.user.IUserInfoService;
import com.cyh.core.login.service.user.IUserService;
import com.cyh.core.framework.common.utils.JWTUtil;
import com.cyh.core.framework.common.utils.MD5Util;
import com.cyh.core.framework.common.utils.RedisUtil;
import com.cyh.core.framework.common.utils.UserTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import java.util.*;


@Service
public class UserServiceImpl implements IUserService {

    @Value("${server.servlet.context-path}")
    String contextPath;

    @Value("${cyh.constant.time.TokenTime}")
    private int tokenTime;

    @Value("${cyh.constant.time.RedisUserTime}")
    private int redisUserTime;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    UserTokenUtil userTokenUtil;

    @Autowired
    UsersRepository usersRepository;

    @Autowired
    IUserInfoService userInfoService;

    @Override
    public ResultDTO userLogin(User user) {
        HttpServletResponse response=(HttpServletResponse)user.getTempObject();
        if( user.getPassword()!=null && user.getUsername()!=null ) {
            user.setPassword(MD5Util.getMd5(user.getPassword()));
            User IdUser=usersRepository.findByUsername(user.getUsername()).get();
            if(IdUser.getPassword().equals(user.getPassword())) {
                Cookie cookie = new Cookie("token", JWTUtil.CreateToken(IdUser, tokenTime));
                cookie.setPath(contextPath);
                cookie.setMaxAge(tokenTime * 60-1);
                response.addCookie(cookie);

                //redisUtil.hset(RedisConstant.LOGIN_USER_HASH,cookie.getValue(),IdUser,redisUserTime*60);
                redisUtil.set(RedisConstant.LOGIN_USER_HASH+":"+cookie.getValue(),IdUser,redisUserTime*60);

                return ResultDTO.Success("Login OK!");
            }
            return ResultDTO.Failure(403,"密码错误");
        }
        return ResultDTO.Failure(500,"Login Error!");
    }

    @Override
    @Transactional
    public ResultDTO userUpdate(User user) {
        HashMap<String,Object> map=(HashMap)user.getTempObject();
        user.setTempObject(null);
        String oldPassword=(String) map.get("oldPassword");
        //HttpServletResponse response=(HttpServletResponse) map.get("response");
        User old= getCurrentUser();//当前操作的用户
        User newU=null;
        boolean isSuper=old.getId().intValue()==0  && user.getId()!=null;
        if(isSuper){
            //当前操作的用户为管理员并且上传了其他人的id
            newU=usersRepository.findById(user.getId()).get();
        }
        else {
            user.setId(old.getId());
        }

        if(user.getUsername()==null){
            if(isSuper){
                user.setUsername(newU.getUsername());
            }else {
                user.setUsername(old.getUsername());
            }
        }

        if(isSuper){
            user.setRoleid(newU.getRoleid());
        }else {
            user.setRoleid(old.getRoleid());
        }

        if( isSuper || old.getPassword().equals(MD5Util.getMd5(oldPassword))){
            user.setPassword(MD5Util.getMd5(user.getPassword()));
            try {
                usersRepository.save(user);
                if(!isSuper) {
                    userLogOut((String) map.get("token"));
                    return ResultDTO.Success("用户更新成功!请重新登录", user);
                }else {
                    return ResultDTO.Success("管理员更新用户成功!",true);
                }
            }catch (Exception e){
                return ResultDTO.Failure(500,"用户更新失败!",e.getMessage());
            }
        }
        else return ResultDTO.Failure(403,"旧密码不正确!");
    }

    @Override
    public ResultDTO userCreate(User user) {
        if( user.getPassword()==null || user.getUsername()==null) {
            return ResultDTO.Failure(403,"请完整输入参数!");
        }
        if(user.getPassword().length()<6){
            return ResultDTO.Failure(403,"密码长度小于6位!");
        }
        Optional<User> optionalUser=usersRepository.findByUsername(user.getUsername());
        if(optionalUser.isPresent()){
            return ResultDTO.Failure(403,"用户名已存在!");
        }
        user.setRoleid(2);
        user.setPassword(MD5Util.getMd5(user.getPassword()));
        try {
            usersRepository.save(user);
            User newUser=usersRepository.findByUsername(user.getUsername()).get();
            UserInfo userInfo=new UserInfo();
            userInfo.setUid(newUser.getId());
            userInfoService.updateUserInfo(userInfo);
            return ResultDTO.Success("用户新增成功!",1);
        }catch (Exception e){
            return ResultDTO.Failure(500,"用户新增失败!",e.getMessage());
        }
    }

    @Override
    public User getUserFromToken(String token) {
        return userTokenUtil.getUserFromToken(token);
    }

    @Override
    public User getCurrentUser() throws NullPointerException{
        return userTokenUtil.getCurrentUser();
    }

    @Override
    public boolean userLogOut(String token) {
        try{
            redisUtil.del(RedisConstant.LOGIN_USER_HASH+":"+token);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    @Override
    public List<User> advancedSearch(SimpleQueryDTO simpleQueryDTO) {
        Map<String,Object> map=simpleQueryDTO.getQueryCondition();
        SimplePageDTO simplePageDTO=simpleQueryDTO.getSimplePageDTO();
        Specification<User> su= (Specification<User>)(root, criteriaQuery, criteriaBuilder)->{
            List<Predicate> predicates = new ArrayList<>();
            Set<String> keys=map.keySet();
            for (String key:keys
                 ) {
                if(key.equals("Username")){
                    predicates.add(criteriaBuilder.like(root.get(key), (String)map.get(key)));
                }else
                predicates.add(criteriaBuilder.equal(root.get(key),map.get(key)));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        return usersRepository.findAll(su,PageRequest.of(simplePageDTO.getPage(),simplePageDTO.getPageSize())).getContent();
    }

}
